/**
 * Convert an Uint8Array into a string.
 * @returns {String}
*/
function Decodeuint8arr(uint8array){
    return new TextDecoder("utf-8").decode(uint8array);
}
    
/**
 * Convert a string into a Uint8Array.
 * @returns {Uint8Array}
 */
function Encodeuint8arr(myString){
    return new TextEncoder("utf-8").encode(myString);
}

// 持续采集数据，并给出分析结果
class ConnectionQuality {
    constructor(options) {
        this.threshold = options.threshold ? options.threshold : ;
        
        this.datas_ = ;

         /**
         * Holds statistics about the local connection quality.
         */
         this._localStats = {
            connectionQuality: 100,
            jvbRTT: undefined
        };

        /**
         * The time this._localStats.connectionQuality was last updated.
         */
        this._lastConnectionQualityUpdate = -1;
    }

    receivePackage(package) {

    }

    getStats() {
        
    }

    
    updateJitter(packet, receive_time_ms) {
        let receive_diff_ms = receive_time_ms - last_receive_time_ms_;
        let time_diff_samples = receive_diff_ms - (packet.Timestamp() - last_received_timestamp_);

        time_diff_samples = Math.abs(time_diff_samples);
    }

    /**
     * Calculates a new "connection quality" value.
     * @param videoType {VideoType} the type of the video source (camera or
     * a screen capture).
     * @param isMuted {boolean} whether the local video is muted.
     * @param resolutionName {Resolution} the input resolution used by the
     * camera.
     * @returns {*} the newly calculated connection quality.
     */
    _calculateConnectionQuality(videoType, isMuted, resolutionName) {
    
        if (isMuted || !resolution || videoType === VideoType.DESKTOP
            || this._timeIceConnected < 0
            || this._timeVideoUnmuted < 0) {

            // Calculate a value based on packet loss only.
            if (packetLoss === undefined) {
                logger.error('Cannot calculate connection quality, unknown '
                    + 'packet loss.');
                quality = 100;
            } else if (packetLoss <= 2) {
                quality = 100; // Full 5 bars.
            } else if (packetLoss <= 4) {
                quality = 70; // 4 bars
            } else if (packetLoss <= 6) {
                quality = 50; // 3 bars
            } else if (packetLoss <= 8) {
                quality = 30; // 2 bars
            } else if (packetLoss <= 12) {
                quality = 10; // 1 bars
            } else {
                quality = 0; // Still 1 bar, but slower climb-up.
            }
        } else {
            // Calculate a value based on the sending bitrate.

            // Figure out if simulcast is in use
            const activeTPC = this._conference.getActivePeerConnection();
            const isSimulcastOn
                = Boolean(activeTPC && activeTPC.isSimulcastOn());

            const newVideoBitrateCap
                = activeTPC && activeTPC.bandwidthLimiter
                && activeTPC.bandwidthLimiter.getBandwidthLimit('video');

            // If we had a cap set but there isn't one now, then it has
            // just been 'lifted', so we should treat this like a new
            // ramp up.
            if (!newVideoBitrateCap && videoBitrateCap) {
                this._timeLastBwCapRemoved = window.performance.now();

                // Set the start bitrate to whatever we were just capped to
                startBitrate = videoBitrateCap;
            }
            videoBitrateCap = newVideoBitrateCap;

            // time since sending of video was enabled.
            const millisSinceStart = window.performance.now()
                - Math.max(this._timeVideoUnmuted,
                    this._timeIceConnected,
                    this._timeLastBwCapRemoved);

            // expected sending bitrate in perfect conditions
            let target
                = getTarget(isSimulcastOn, resolution, millisSinceStart);

            target = Math.min(0.9 * target, MAX_TARGET_BITRATE);

            if (videoBitrateCap) {
                target = Math.min(target, videoBitrateCap);
            }

            quality = 100 * this._localStats.bitrate.upload / target;

            // Whatever the bitrate, drop early if there is significant loss
            if (packetLoss && packetLoss >= 10) {
                quality = Math.min(quality, 30);
            }
        }

        // Make sure that the quality doesn't climb quickly
        if (this._lastConnectionQualityUpdate > 0) {
            const maxIncreasePerSecond = 2;
            const prevConnectionQuality = this._localStats.connectionQuality;
            const diffSeconds
                = (window.performance.now() - this._lastConnectionQualityUpdate)
                    / 1000;

            quality
                = Math.min(
                    quality,
                    prevConnectionQuality
                        + (diffSeconds * maxIncreasePerSecond));
        }

        return Math.min(100, quality);
    }

    collect_data() {

    }
    qulity() {

    }
}




// 当前推送者的工作状态
// 如果发现质量有问题，立即使用后背的，并将当前节点放到partner里面，同时追查该节点的质量，如果特别不好，则放在候选者里面
// 质量评估： 延迟  卡顿  丢包  带宽
// 先实现简单的模型，以后借鉴相关项目的计算方式
// 每种都分优良中差， 差的会作为门槛影响总体
// 门槛值： delay延迟 200ms（单向）  card卡顿 （100ms）   lost丢包 (10%)  bandwidth带宽 (排除付费的， 总带宽的60% < 1路音视频的)
// 每隔300ms检查一次pusher，  总评公式：  delay / 200    card / 100   lost/10   bd / ...
// 单独一项如果超过 100% 则直接置为不可用；    
// (delay / 200  +   card / 100 +  lost/10 )  /  3
class PusherState {
    constructor() {
        this.push_start_time = Date.now();
        this.last_received_data_time = 0;

        this.delay_ = 0;
        this.card_ = 0;

    }

    qulity()
}
